/**
 * @file gameservicediscovery.cpp
 * @brief 游戏服务发现类实现文件
 *
 * 实现与API Gateway服务发现API的完整集成，提供：
 * - 按游戏类型筛选服务列表
 * - 健康状态检查和筛选
 * - 自动刷新和错误处理机制
 */

#include "../include/gameservicediscovery.h"
#include "../include/config.h"
#include <QDebug>
#include <QJsonParseError>
#include <QDateTime>

/**
 * @brief GameServiceDiscovery构造函数
 * @param apiGatewayUrl API Gateway的基础URL
 * @param parent 父对象指针
 *
 * 初始化服务发现客户端的所有组件：
 * 1. 创建网络访问管理器
 * 2. 设置基础URL和配置参数
 * 3. 初始化自动刷新定时器
 * 4. 设置支持的游戏类型列表
 */
GameServiceDiscovery::GameServiceDiscovery(const QString& apiGatewayUrl, QObject* parent)
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this))
    , m_apiGatewayUrl(apiGatewayUrl)
    , m_refreshTimer(new QTimer(this))
    , m_currentHealthyOnly(true)
    , m_requestTimeout(30000)  // 30秒超时
    , m_isQueryInProgress(false)
{
    // === 设置网络管理器 ===
    m_networkManager->setTransferTimeout(m_requestTimeout);

    // === 配置自动刷新定时器 ===
    m_refreshTimer->setSingleShot(false);  // 重复定时器
    connect(m_refreshTimer, &QTimer::timeout, this, &GameServiceDiscovery::refreshServices);

    // === 初始化支持的游戏类型 ===
    m_supportedGameTypes << "snake" << "tetris" << "puzzle" << "chess" << "custom";

    qDebug() << "GameServiceDiscovery: 初始化完成，API Gateway URL:" << m_apiGatewayUrl;
}

/**
 * @brief 按游戏类型获取服务列表
 * @param gameType 游戏类型（snake、tetris等）
 * @param healthyOnly 是否只返回健康的服务
 *
 * 发起按游戏类型筛选的服务发现请求
 */
void GameServiceDiscovery::getServicesByGameType(const QString& gameType, bool healthyOnly)
{
    if (m_isQueryInProgress) {
        qWarning() << "GameServiceDiscovery: 已有查询正在进行中，忽略新请求";
        return;
    }

    m_currentGameType = gameType;
    m_currentServiceName.clear();
    m_currentHealthyOnly = healthyOnly;
    
    QString queryDesc = generateQueryDescription(gameType, "", healthyOnly);
    emit discoveryStarted(queryDesc);
    
    qDebug() << "GameServiceDiscovery: 开始按游戏类型查询服务:" << gameType << "健康状态:" << healthyOnly;
    makeRequest(gameType, "", healthyOnly);
}

/**
 * @brief 获取所有服务
 * @param healthyOnly 是否只返回健康的服务
 *
 * 获取所有已注册的游戏服务，不进行游戏类型筛选
 */
void GameServiceDiscovery::getAllServices(bool healthyOnly)
{
    if (m_isQueryInProgress) {
        qWarning() << "GameServiceDiscovery: 已有查询正在进行中，忽略新请求";
        return;
    }

    m_currentGameType.clear();
    m_currentServiceName.clear();
    m_currentHealthyOnly = healthyOnly;
    
    QString queryDesc = generateQueryDescription("", "", healthyOnly);
    emit discoveryStarted(queryDesc);
    
    qDebug() << "GameServiceDiscovery: 开始查询所有服务，健康状态:" << healthyOnly;
    makeRequest("", "", healthyOnly);
}

/**
 * @brief 按服务名称获取服务列表
 * @param serviceName 服务名称
 * @param healthyOnly 是否只返回健康的服务
 *
 * 按特定服务名称筛选服务实例
 */
void GameServiceDiscovery::getServicesByName(const QString& serviceName, bool healthyOnly)
{
    if (m_isQueryInProgress) {
        qWarning() << "GameServiceDiscovery: 已有查询正在进行中，忽略新请求";
        return;
    }

    m_currentGameType.clear();
    m_currentServiceName = serviceName;
    m_currentHealthyOnly = healthyOnly;
    
    QString queryDesc = generateQueryDescription("", serviceName, healthyOnly);
    emit discoveryStarted(queryDesc);
    
    qDebug() << "GameServiceDiscovery: 开始按服务名称查询:" << serviceName << "健康状态:" << healthyOnly;
    makeRequest("", serviceName, healthyOnly);
}

/**
 * @brief 发起HTTP请求
 * @param gameType 游戏类型（可选）
 * @param serviceName 服务名称（可选）
 * @param healthyOnly 是否只返回健康的服务
 *
 * 构建服务发现API请求并发送
 */
void GameServiceDiscovery::makeRequest(const QString& gameType, const QString& serviceName, bool healthyOnly)
{
    // === 构建请求URL ===
    QUrl url(m_apiGatewayUrl + "/api/v1/services");
    QUrlQuery query;
    
    // 添加查询参数
    if (!gameType.isEmpty()) {
        query.addQueryItem("game_type", gameType);
    }
    if (!serviceName.isEmpty()) {
        query.addQueryItem("service", serviceName);
    }
    if (healthyOnly) {
        query.addQueryItem("healthy", "true");
    }

    // === 添加游戏服务筛选条件 ===
    // 根据服务发现API文档，添加筛选条件确保只获取游戏服务
    if (serviceName.isEmpty()) {
        // 如果没有指定特定服务名称，则添加游戏服务的筛选模式
        // 使用更宽松的模式，支持多种命名方式
        query.addQueryItem("service_pattern", "*game*,*snake*,*tetris*,*puzzle*");
    }
    
    // 排除认证服务和API网关 - 使用更精确的排除列表
    if (serviceName.isEmpty()) {
        query.addQueryItem("exclude_services", "auth_service,api_gateway_service,mysql,redis,kafka");
    }
    
    url.setQuery(query);
    
    // === 创建网络请求 ===
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setRawHeader("Accept", "application/json");
    request.setRawHeader("User-Agent", QString("%1/%2").arg(Config::getAppName(), Config::getAppVersion()).toUtf8());
    
    // === 发送GET请求 ===
    m_isQueryInProgress = true;
    QNetworkReply* reply = m_networkManager->get(request);
    connect(reply, &QNetworkReply::finished, this, &GameServiceDiscovery::handleNetworkReply);
    
    // === 设置超时处理 ===
    QTimer::singleShot(m_requestTimeout, reply, [reply, this]() {
        if (reply->isRunning()) {
            reply->abort();
            m_isQueryInProgress = false;
            emit networkError("请求超时：服务发现API未在规定时间内响应");
        }
    });
    
    qDebug() << "GameServiceDiscovery: 发送服务发现请求:" << url.toString();
}

/**
 * @brief 处理网络响应
 *
 * 处理服务发现API的响应，解析JSON数据并发出相应信号
 */
void GameServiceDiscovery::handleNetworkReply()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) {
        m_isQueryInProgress = false;
        return;
    }
    
    reply->deleteLater();
    m_isQueryInProgress = false;
    
    // === 检查网络错误 ===
    if (reply->error() != QNetworkReply::NoError) {
        QString error = QString("网络错误: %1 (代码: %2)")
                       .arg(reply->errorString())
                       .arg(static_cast<int>(reply->error()));
        emit networkError(error);
        qWarning() << "GameServiceDiscovery:" << error;
        return;
    }
    
    // === 读取响应数据 ===
    QByteArray data = reply->readAll();
    if (data.isEmpty()) {
        emit errorOccurred("收到空响应", "EMPTY_RESPONSE");
        qWarning() << "GameServiceDiscovery: 收到空响应";
        return;
    }
    
    // === 调试：输出原始响应数据 ===
    qDebug() << "GameServiceDiscovery: 收到响应数据:" << data;
    
    // === 解析JSON ===
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(data, &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        QString error = QString("JSON解析错误: %1 (偏移: %2)")
                       .arg(parseError.errorString())
                       .arg(parseError.offset);
        emit errorOccurred(error, "PARSE_ERROR");
        qWarning() << "GameServiceDiscovery:" << error;
        qDebug() << "原始响应数据:" << data;
        return;
    }
    
    // === 检查API响应状态 ===
    QJsonObject response = doc.object();
    
    if (!response["success"].toBool()) {
        QString errorCode = response["error_code"].toString();
        QString errorMessage = response["message"].toString();
        if (errorMessage.isEmpty()) {
            errorMessage = "服务发现请求失败";
        }
        emit errorOccurred(errorMessage, errorCode);
        qWarning() << "GameServiceDiscovery: API错误:" << errorCode << errorMessage;
        return;
    }
    
    // === 解析服务列表 ===
    QList<GameServiceInfo> services = parseServicesResponse(response);
    
    // === 创建查询信息 ===
    QJsonObject queryInfo;
    if (response.contains("data") && response["data"].toObject().contains("filters")) {
        queryInfo = response["data"].toObject()["filters"].toObject();
    }
    queryInfo["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
    queryInfo["service_count"] = services.size();
    
    // === 发出成功信号 ===
    emit servicesReceived(services, m_currentGameType, queryInfo);
    
    qDebug() << "GameServiceDiscovery: 成功获取" << services.size() << "个服务"
             << "游戏类型:" << m_currentGameType;
}

/**
 * @brief 解析服务响应
 * @param response API响应JSON对象
 * @return 解析后的服务列表
 *
 * 解析服务发现API的响应数据，提取服务列表
 */
QList<GameServiceInfo> GameServiceDiscovery::parseServicesResponse(const QJsonObject& response)
{
    QList<GameServiceInfo> services;
    
    // === 提取服务数组 ===
    QJsonObject data = response["data"].toObject();
    QJsonArray servicesArray = data["services"].toArray();
    
    if (servicesArray.isEmpty()) {
        qDebug() << "GameServiceDiscovery: 响应中没有服务数据";
        return services;
    }
    
    // === 解析每个服务 ===
    for (const QJsonValue& value : servicesArray) {
        QJsonObject serviceObj = value.toObject();
        GameServiceInfo service = parseServiceInfo(serviceObj);

        // 验证服务信息的有效性并过滤非游戏服务
        if (validateServiceInfo(service) && isGameService(service)) {
            services.append(service);
        } else {
            qDebug() << "GameServiceDiscovery: 跳过非游戏服务或无效服务:" << service.serviceName;
        }
    }
    
    qDebug() << "GameServiceDiscovery: 解析了" << servicesArray.size() << "个服务，有效服务" << services.size() << "个";
    return services;
}

/**
 * @brief 解析单个服务信息
 * @param serviceObj 服务JSON对象
 * @return 解析后的服务信息
 *
 * 将JSON对象转换为GameServiceInfo结构体
 */
GameServiceInfo GameServiceDiscovery::parseServiceInfo(const QJsonObject& serviceObj)
{
    GameServiceInfo info;
    
    // === 基本服务信息 ===
    info.serviceName = serviceObj["service_name"].toString();
    info.serviceVersion = serviceObj["service_version"].toString();
    info.host = serviceObj["host"].toString();
    info.port = serviceObj["port"].toInt();
    info.healthCheckEndpoint = serviceObj["health_check_endpoint"].toString();
    info.lastHeartbeat = serviceObj["last_heartbeat"].toString();
    info.healthy = serviceObj["healthy"].toBool();
    info.weight = serviceObj["weight"].toInt();
    info.metadata = serviceObj["metadata"].toObject();
    
    // === 解析端点列表 ===
    QJsonArray endpointsArray = serviceObj["endpoints"].toArray();
    for (const QJsonValue& endpoint : endpointsArray) {
        info.endpoints.append(endpoint.toString());
    }
    
    return info;
}

/**
 * @brief 验证服务信息有效性
 * @param service 服务信息
 * @return 是否有效
 *
 * 检查服务信息的必要字段是否完整
 */
bool GameServiceDiscovery::validateServiceInfo(const GameServiceInfo& service) const
{
    // 检查必要字段
    if (service.serviceName.isEmpty()) {
        qWarning() << "服务名称为空";
        return false;
    }
    
    if (service.host.isEmpty()) {
        qWarning() << "主机地址为空";
        return false;
    }
    
    if (service.port <= 0 || service.port > 65535) {
        qWarning() << "端口号无效:" << service.port;
        return false;
    }
    
    return true;
}

/**
 * @brief 自动刷新间隔设置
 * @param seconds 刷新间隔（秒）
 */
void GameServiceDiscovery::setAutoRefreshInterval(int seconds)
{
    if (seconds > 0) {
        m_refreshTimer->setInterval(seconds * 1000);
        qDebug() << "GameServiceDiscovery: 设置自动刷新间隔为" << seconds << "秒";
    } else {
        m_refreshTimer->setInterval(0);
        qDebug() << "GameServiceDiscovery: 禁用自动刷新";
    }
}

/**
 * @brief 启动自动刷新
 */
void GameServiceDiscovery::startAutoRefresh()
{
    if (m_refreshTimer->interval() > 0) {
        m_refreshTimer->start();
        qDebug() << "GameServiceDiscovery: 启动自动刷新，间隔" << (m_refreshTimer->interval() / 1000) << "秒";
    } else {
        qWarning() << "GameServiceDiscovery: 未设置刷新间隔，无法启动自动刷新";
    }
}

/**
 * @brief 停止自动刷新
 */
void GameServiceDiscovery::stopAutoRefresh()
{
    m_refreshTimer->stop();
    qDebug() << "GameServiceDiscovery: 停止自动刷新";
}

/**
 * @brief 自动刷新槽函数
 *
 * 定时器触发时自动重新执行上次的查询
 */
void GameServiceDiscovery::refreshServices()
{
    if (m_isQueryInProgress) {
        qDebug() << "GameServiceDiscovery: 查询正在进行中，跳过自动刷新";
        return;
    }

    qDebug() << "GameServiceDiscovery: 执行自动刷新";
    
    if (!m_currentGameType.isEmpty()) {
        makeRequest(m_currentGameType, "", m_currentHealthyOnly);
    } else if (!m_currentServiceName.isEmpty()) {
        makeRequest("", m_currentServiceName, m_currentHealthyOnly);
    } else {
        makeRequest("", "", m_currentHealthyOnly);
    }
}

/**
 * @brief 手动刷新当前查询
 */
void GameServiceDiscovery::refreshCurrentQuery()
{
    if (m_isQueryInProgress) {
        qWarning() << "GameServiceDiscovery: 查询正在进行中，无法手动刷新";
        return;
    }

    qDebug() << "GameServiceDiscovery: 执行手动刷新";
    refreshServices();
}

/**
 * @brief 获取支持的游戏类型列表
 * @return 游戏类型列表
 */
QStringList GameServiceDiscovery::getSupportedGameTypes() const
{
    return m_supportedGameTypes;
}

/**
 * @brief 检查服务是否可用
 * @param service 服务信息
 * @return 是否可用
 */
bool GameServiceDiscovery::isServiceAvailable(const GameServiceInfo& service) const
{
    return service.healthy && validateServiceInfo(service);
}

/**
 * @brief 判断是否为游戏服务
 * @param service 服务信息
 * @return 是否为游戏服务
 */
bool GameServiceDiscovery::isGameService(const GameServiceInfo& service) const
{
    // 检查服务名称是否包含游戏服务的特征
    QString serviceName = service.serviceName.toLower();

    // === 严格排除非游戏服务 ===
    // 排除认证服务
    if (serviceName.contains("auth") || serviceName.contains("authentication") ||
        serviceName.contains("login") || serviceName.contains("user")) {
        qDebug() << "GameServiceDiscovery: 排除认证服务:" << service.serviceName;
        return false;
    }

    // 排除API网关和基础设施服务
    if (serviceName.contains("gateway") || serviceName.contains("api_gateway") ||
        serviceName.contains("proxy") || serviceName.contains("load_balancer") ||
        serviceName.contains("registry") || serviceName.contains("discovery")) {
        qDebug() << "GameServiceDiscovery: 排除基础设施服务:" << service.serviceName;
        return false;
    }

    // 排除数据库和消息服务
    if (serviceName.contains("mysql") || serviceName.contains("redis") ||
        serviceName.contains("kafka") || serviceName.contains("database") ||
        serviceName.contains("message") || serviceName.contains("queue")) {
        qDebug() << "GameServiceDiscovery: 排除数据库/消息服务:" << service.serviceName;
        return false;
    }

    // === 积极识别游戏服务 ===
    // 首先检查元数据中的游戏类型（最可靠的方式）
    if (service.metadata.contains("game_type")) {
        QString gameType = service.metadata["game_type"].toString().toLower();
        if (!gameType.isEmpty() && gameType != "none" && gameType != "null") {
            qDebug() << "GameServiceDiscovery: 识别为游戏服务（通过game_type）:" << service.serviceName << "类型:" << gameType;
            return true;
        }
    }

    // 检查服务名称是否明确为游戏服务 - 更宽松的条件
    if (serviceName.contains("game") || serviceName.contains("snake") ||
        serviceName.contains("tetris") || serviceName.contains("puzzle") ||
        serviceName.contains("room") || serviceName.contains("player")) {
        qDebug() << "GameServiceDiscovery: 识别为游戏服务（通过服务名称）:" << service.serviceName;
        return true;
    }

    // 检查端点是否包含游戏相关路径
    for (const QString& endpoint : service.endpoints) {
        if (endpoint.contains("/snake/") || endpoint.contains("/tetris/") ||
            endpoint.contains("/puzzle/") || endpoint.contains("/game/rooms") ||
            endpoint.contains("/ws/snake") || endpoint.contains("/ws/tetris") ||
            endpoint.contains("/leaderboard") || endpoint.contains("/rooms/public")) {
            qDebug() << "GameServiceDiscovery: 识别为游戏服务（通过端点）:" << service.serviceName;
            return true;
        }
    }

    // 检查元数据中的其他游戏相关信息
    if (service.metadata.contains("max_players") || service.metadata.contains("room_capacity") ||
        service.metadata.contains("game_mode") || service.metadata.contains("player_count")) {
        qDebug() << "GameServiceDiscovery: 识别为游戏服务（通过游戏元数据）:" << service.serviceName;
        return true;
    }

    qDebug() << "GameServiceDiscovery: 无法识别为游戏服务，排除:" << service.serviceName;
    return false;
}

/**
 * @brief 生成查询描述
 * @param gameType 游戏类型
 * @param serviceName 服务名称
 * @param healthyOnly 是否只查询健康服务
 * @return 查询描述字符串
 */
QString GameServiceDiscovery::generateQueryDescription(const QString& gameType, const QString& serviceName, bool healthyOnly) const
{
    QStringList parts;

    if (!gameType.isEmpty()) {
        parts << QString("游戏类型: %1").arg(gameType);
    }
    if (!serviceName.isEmpty()) {
        parts << QString("服务名称: %1").arg(serviceName);
    }

    parts << QString("健康状态: %1").arg(healthyOnly ? "仅健康服务" : "所有服务");

    return parts.join(", ");
}

